`timescale 1ns / 1ns
`ifndef __CPU_DEFINES_SV
`define __CPU_DEFINES_SV
`include "./common.sv"

`define CPU_DEBUG
`ifdef CPU_DEBUG
	`define ROB_DEBUG
`endif 
// `define PERFORMENCE_TEST

`define RST_ENABLE      1'b0                
`define RST_DISABLE     1'b1                
        
`define SHIFT_ENABLE    1'b1                
`define ALUTYPE_BUS     2 : 0               

`define CHIP_ENABLE     1'b1                
`define CHIP_DISABLE    1'b0                

`define RT_ENABLE       1'b1                
`define SIGNED_EXT      1'b1                
`define IMM_ENABLE      1'b1                
`define UPPER_ENABLE    1'b1                
`define MREG_ENABLE     1'b1                
`define BSEL_BUS        3 : 0               
`define PC_INIT         32'hbfc00000 
// `define PC_INIT 		32'hbfbf_fffc

`define INST_INDEX_BUS  25:0

`define LOAD_RAM        1'b1
`define LOAD_ALU        1'b0

`define ALU_INST_BUS    2:0

`define INST_INIT       32'h00000000    
`define MEM_MASK 32'h1fffffff 

/*-------------------BarrierController--------------*/

`define STAGE_SIZE 5

/*------------------- ָinstBuffer -------------------*/
`define INSTBUFFER_SIZE 4'b1000
`define INST_BUFFER_WIDTH 3


`define NOP             3'b000
`define ARITH           3'b001
`define LOGIC           3'b010
`define SHIFT           3'b100
`define MOVE            3'b011
`define JUMP            3'b101

// `define isue_mode_t enum{INIT_ISSUE, SIGNLE_ISSUE, DUAL_ISSUE}
`define INIT_ISSUE 2'b00
`define DUAL_ISSUE 2'b10
`define SINGLE_ISSUE 2'b01


/*----------------------------DCU------------------------------------*/
`define ALL_and_INST 		(inst_and | inst_andi)
`define ALL_or_INST       	(inst_or | inst_ori )
`define ALL_xor_INST 	  	(inst_xor | inst_xori )
`define ALL_add_INST     	(inst_add  | inst_addi | inst_addu | inst_addiu)
`define ALL_sub_INST 	  	(inst_sub | inst_subu )
`define ALL_slt_INST 		(inst_slt | inst_slti | inst_sltu | inst_sltiu)
`define ALL_jmp_INST	  	(inst_j | inst_jal | inst_jr | inst_jalr) 
`define ALL_bne_INST 	  	(inst_beq | inst_bne | inst_bgez | inst_bgtz | inst_blez |\
							 inst_bltz | inst_bgezal | inst_bltzal)

`define ALL_ARITH_INST  	(`ALL_add_INST | `ALL_sub_INST | `ALL_slt_INST )
`define ALL_LOGIC_INST 		(inst_and | inst_andi | inst_nor | inst_or | inst_ori | inst_xor | inst_xori)
`define ALL_SHIFT_INST  	(inst_sll | inst_sllv | inst_sra | inst_srav | inst_srl | inst_srlv )
`define ALL_LMEM_INST 		(inst_lb | inst_lbu | inst_lh | inst_lhu | inst_lw )
`define ALL_SMEM_INST 		(inst_sb | inst_sh | inst_sw)
`define ALL_MEM_INST   		(`ALL_LMEM_INST | `ALL_SMEM_INST) 
`define ALL_IMM_INST    	(inst_addi | inst_addiu | inst_slti | inst_sltiu | inst_andi | inst_lui | inst_ori | inst_xori )
`define ALL_INST 			(inst_add    |inst_addi  |inst_addu |inst_addiu | \
							inst_sub    |inst_subu  |		\
							inst_slt    |inst_slti  |inst_sltu |inst_sltiu |\
							inst_mult   |inst_multu |inst_div  |inst_divu |\
							inst_and    |inst_andi  |inst_lui  |\
							inst_nor    |inst_or    |inst_ori  |inst_xor  |inst_xori    |\
							inst_sll    |inst_sllv  |inst_sra  |inst_srav   |inst_srl  |inst_srlv    |\
							inst_mfhi   |inst_mflo  |inst_mthi |inst_mtlo |\
							inst_lb     |inst_lbu   |inst_lh   |inst_lhu   |inst_lw   |\
							inst_sb     |inst_sh    |inst_sw   |\
							inst_jal    |inst_j     |inst_jr   |inst_jalr   |\
							inst_beq    |inst_bne   |inst_bgez |inst_bgtz   |\
							inst_blez   |inst_bltz  |inst_bgezal |inst_bltzal |\
							inst_mfc0   |inst_mtc0  |inst_syscall|inst_eret   |inst_break)

`define ALUOP_SIZE 8
`define ALUOP_BUS 7: 0
`define ALUOP_MTLO	8'b0000_0001
`define ALUOP_MTHI	8'b0000_0010
`define ALUOP_LUI	8'b0000_0101
`define ALUOP_MFHI	8'b0000_1100
`define ALUOP_MFLO	8'b0000_1101

`define ALUOP_ADDI 	8'b0001_0000
`define ALUOP_SLL	8'b0001_0001
`define ALUOP_ADDU 	8'b0001_0010
`define ALUOP_SUB 	8'b0001_0011
`define ALUOP_ANDI	8'b0001_0110
`define ALUOP_ADD 	8'b0001_1000
`define ALUOP_ADDIU 8'b0001_1001
`define ALUOP_XOR	8'b0001_1010
`define ALUOP_SUBU	8'b0001_1011
`define ALUOP_AND	8'b0001_1100
`define ALUOP_ORI	8'b0001_1101

`define ALUOP_SLTI	8'b0010_0000
`define ALUOP_SLTU	8'b0010_0001
`define ALUOP_SLT	8'b0010_0010
`define ALUOP_SLTIU 8'b0010_0100
`define ALUOP_JR	8'b0010_1000
`define ALUOP_JAL	8'b0010_1001

`define ALUOP_NOR	8'b0100_0000
`define ALUOP_OR	8'b0100_0001
`define ALUOP_XORI	8'b0100_0010
`define ALUOP_SLLV	8'b0100_0100
`define ALUOP_SRA	8'b0100_1000
`define ALUOP_SRAV	8'b0100_0011
`define ALUOP_SRL	8'b0100_0110
`define ALUOP_SRLV	8'b0100_1100

`define ALUOP_MUL 	8'b0011_0010
`define ALUOP_RLWINM 8'b0011_0011

`define ALUOP_MOVN 	8'b1000_0000
`define ALUOP_MOVZ	8'b1000_0010
`define ALUOP_CLO	8'b1000_0100
`define ALUOP_CLZ	8'b1000_1000

`define ALUOP_BEQ		8'b1010_0001
`define ALUOP_BNE 		8'b1010_0010
`define ALUOP_BGEZ		8'b1010_0100
`define ALUOP_JALR		8'b1010_0101
`define ALUOP_BGEZAL	8'b1010_0110
`define ALUOP_BLTZ		8'b1010_1000
`define ALUOP_BLTZAL	8'b1010_1001
`define ALUOP_BLEZ		8'b1010_1010
`define ALUOP_BGTZ		8'b1010_1100


`define ALUOP_TLT		8'b1100_0000
`define ALUOP_TLTU		8'b1100_0001
`define ALUOP_TGE       8'b1100_0010
`define ALUOP_TGEU      8'b1100_0011
`define ALUOP_TEQ 		8'b1100_0100
`define ALUOP_TNE		8'b1100_0101

`define ALUOP_MATCH 	8'b1111_1001

`define MULTOP_SIZE 4
`define MULTOP_BUS 3: 0
`define MULTOP_MULT 	4'b0000
`define MULTOP_MULTU 	4'b0001
`define MULTOP_MSUB		4'b0010
`define MULTOP_MUL 		4'b0011
`define MULTOP_MADD		4'b0100
`define MULTOP_MADDU 	4'b0101
`define MULTOP_DIV		4'b0110
`define MULTOP_DIVU 	4'b0111
`define MULTOP_MSUBU 	4'b1000

`define MEMOP_SIZE 5
`define MEMOP_BUS 4: 0
`define MEMOP_LB	5'b00000
`define MEMOP_LBU 	5'b00100
`define MEMOP_LH 	5'b00001 
`define MEMOP_LHU 	5'b00101
`define MEMOP_LW 	5'b00010
`define MEMOP_SB 	5'b10000 
`define MEMOP_SH 	5'b10001
`define MEMOP_SW 	5'b10010
`define MEMOP_LWL 	5'b01010
`define MEMOP_LWR 	5'b01110
`define MEMOP_SWL 	5'b11010
`define MEMOP_SWR 	5'b11110
`define MEMOP_LL 	5'b00110
`define MEMOP_SC 	5'b10110

`define CP0OP_SIZE 	3
`define CP0OP_BUS	2:0
`define CP0OP_CACHE	3'b000
`define CP0OP_MTC0 	3'b001
`define CP0OP_MFC0 	3'b010
`define CP0OP_TLBP 	3'b011
`define CP0OP_TLBR	3'b100
`define CP0OP_TLBWI 3'b101
`define CP0OP_TLBWR 3'b110
`define CP0OP_WAIT	3'b111

`define HALFWORD_NOT_ALIGN(daddr)       (daddr[0])
`define WORD_NOT_ALIGN(daddr)           (daddr[1]|daddr[0])     
              
`define REG_ADDR_BUS    4 : 0                                
`define REG_NOP         5'b00000            

// INST_TYPE
`define INST_TYPE_SIZE 3
// `define INST_TYPE_NONE 3'b0
`define INST_TYPE_BUS 2: 0
`define INST_TYPE_ALU 		3'b000
`define INST_TYPE_MULT 		3'b001
`define INST_TYPE_BRANCH 	3'b010
`define INST_TYPE_MEM 		3'b011
`define INST_TYPE_CP0 		3'b100
`define INST_TYPE_TLB 		3'b101

/*----------------PRF----------------*/
`define PRF_SIZE 64

/*----------------ROB----------------*/
`define ROB_SIZE 64

/*-----------------REG---------------*/
`define REG_SIZE 6
`define REG_BUS 5: 0
`define REG_NUM 6'd34
`define REG_HI 6'b100000
`define REG_LO 6'b100001

/*--------FunctionUnitNumber----------*/
`define UNIT_ALU1 3'b1
`define UNIT_ALU2 3'b10
`define UNIT_MULT 3'b11
`define UNIT_MEM 3'b100
`define UNIT_CP0 3'b101

/*----------BranchPredict------------*/
`define branch_predict_len 7
`define branch_predict_start 5
`define BHR_num 6

/*--------------CP0 reg-----------*/
`define Index 		0 	
`define Random 		1
`define EntryLo0 	2
`define EntryLo1 	3
`define Context 	4
`define PageMask    5
`define Wired 		6
`define BadVaddr    8
`define Count       9 
`define EntryHi 	10
`define Compare     11
`define Status      12
`define Cause       13
`define EPC         14
`define PRid 		15	
`define _Config 	16
`define Taglo 		28
`define Taghi 		29
`define ErrorEpc 	30
`define Config1 	32+16
`define Ebase 		47 // 32 + 15

`define CAUSE_EXCCODE 6:2
`define STATUS_EXL  1
`define STATUS_IE   0
`define CAUSE_BD 	31
/*---------------ExcCode-----------*/

`define EXC_CODE_BUS    4:0
`define EXC_REG_BUS		4:0
`define EXC_INT         5'h00
`define EXC_SYS         5'h08
`define EXC_OV          5'h0c
`define EXC_NONE        5'h10
`define EXC_ERET        5'h11
`define EXC_BREAK       5'h09
`define EXC_AdEL        5'h04
`define EXC_AdES        5'h05
`define EXC_RI          5'h0a
`define EXC_CpU			5'h0b
`define EXC_TR 			5'h0d
`define EXC_MOD 		5'h01
`define EXC_TLBL 		5'h02
`define EXC_TLBS 		5'h03
`define EXC_RTLBL 		5'h15
`define EXC_ITLBL 		5'h16 
`define EXC_RTLBS 		5'h17 
`define EXC_ITLBS 		5'h18
`define EXC_FLUSH 		5'h1f // 自己定义的，用于MOVN, MOVZ指令失败之后清空流水线


`define EXC_TLB_ADDR 	32'hbfc0_0200
`define EXC_ADDR        32'hbfc0_0380
`define EXC_INT_ADDR    32'hbfc0_0380
// TLB
`define TAG_WIDTH 20
`define TLB_NUM 32
`define TLB_WIDTH $clog2(`TLB_NUM) - 1 : 0

// all module define
`define IDRAT_REG_DEFINE(num) \
	IDRAT_reg IDRAT_REG_``num(\
		.cpu_clk(clk),\
		.stall(rat_stall | dis_stall_req),\
		.clear(id_clear[num-1]),\
		.id_inst_rs(id_inst``num``_rs),\
		.id_inst_rt(id_inst``num``_rt),\
		.id_inst_rd(id_inst``num``_rd),\
		.id_inst_src1(id_inst``num``_src1),\
		.id_inst_src2(id_inst``num``_src2),\
		.id_inst_type(id_inst``num``_type),\
		.id_inst_aluop(id_inst``num``_aluop),\
		.id_inst_en(id_inst``num``_en),\
		.id_inst_memop(id_inst``num``_memop),\
		.id_inst_exccode(id_inst``num``_exccode),\
		.id_inst_cp0op(id_inst``num``_cp0op),\
		.id_inst_multop(id_inst``num``_multop),\
		.id_inst_place2(id_inst``num``_place2),\
		.id_inst_branch(id_inst``num``_branch),\
		.id_inst_rasup(id_inst``num``_rasup),\
		.id_inst_rasdown(id_inst``num``_rasdown),\
		`ifdef CPU_DEBUG \
			.debug_idrat_inst_in(instBuffer_inst``num``),\
			.debug_idrat_addr_in(instBuffer_iaddr``num``), \
			.debug_idrat_inst_out(debug_idrat_inst``num``_out),\
			.debug_idrat_addr_out(debug_idrat_addr``num``_out), \
		`endif \
		.rat_inst_rs(rat_inst``num``_rs),\
		.rat_inst_rt(rat_inst``num``_rt),\
		.rat_inst_rd(rat_inst``num``_rd),\
		.rat_inst_src1(rat_inst``num``_src1),\
		.rat_inst_src2(rat_inst``num``_src2),\
		.rat_inst_type(rat_inst``num``_type),\
		.rat_inst_aluop(rat_inst``num``_aluop),\
		.rat_inst_en(rat_inst``num``_en),\
		.rat_inst_memop(rat_inst``num``_memop),\
		.rat_inst_exccode(rat_inst``num``_exccode),\
		.rat_inst_cp0op(rat_inst``num``_cp0op),\
		.rat_inst_multop(rat_inst``num``_multop),\
		.rat_inst_branch(rat_inst``num``_branch),\
		.rat_inst_place2(rat_inst``num``_place2),\
		.rat_inst_rasup(rat_inst``num``_rasup),\
		.rat_inst_rasdown(rat_inst``num``_rasdown)\
	);\

`define  CONVERSE32(varName) assign varName = {varName[7:0], varName[15:8], varName[23:16], varName[31:24]}
`define  DEBUG

`define  ASSERT(cond)  \
		`ifdef DEBUG	\
		always_comb begin \
			if((~(cond))) begin \
				$display("Assert False"); \
        		$finish(); \
			end 			\
		end 				\
		`endif \
//misc 

`define TAGE_TABLE_SIZE 10
`define TAGE_TABLE_WIDTH $clog2(`TAGE_TABLE_SIZE)
`define PREDICT_TABLE_SIZE 11
`define PREDICTOR_INDEX_SIZE 10
`define PREDICTOR_BASE_INDEX_SIZE 12
`define PREDICTOR_TAG_SIZE 9
`define BRANCH_BUFFER_SIZE 16
`define BRANCH_BUFFER_WIDTH $clog2(`BRANCH_BUFFER_SIZE)
typedef struct packed {
	logic predict;
	logic alt_predict;
	logic new_entry;
	logic table_hit;
	logic btb_en;
	logic [`PREDICT_TABLE_SIZE-1: 0] providers;
	logic [`PREDICT_TABLE_SIZE-1: 0] alt_provider;
	logic [`PREDICTOR_BASE_INDEX_SIZE-1: 0] base_index;
	logic [`TAGE_TABLE_SIZE-1: 0][`PREDICTOR_INDEX_SIZE-1: 0] index;
	logic [`TAGE_TABLE_SIZE-1: 0][`PREDICTOR_TAG_SIZE-1: 0] tag;
	logic [31: 0] btb_addr;
} BranchInfo;

typedef struct packed {
	logic branch;
	logic store;
	logic multdiv;
	logic j;
	logic exception;
	logic ras_we;
	logic ras_re;
	logic jalr;
	logic [1: 0] analyze_result;
	// logic [31: 0] analyze_addr;
} InstInfoBundle;
`endif
            
